package com.antexpress.dao;

import com.antexpress.pojo.Employee;
import com.antexpress.pojo.ExpressDistribution;
import com.antexpress.pojo.MapCity;
import com.antexpress.pojo.MapDistrict;
import com.antexpress.pojo.MapProvince;
import com.antexpress.pojo.MapTown;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

@Repository
public class CourierDAOImpl implements CourierDAO{
    @Autowired  
    private SessionFactory sessionFactory;
    
    private Session getSession(){ 
        return sessionFactory.getCurrentSession();
    }  
    
    public int getAllRowCount() {
        Session session = getSession();
        Criteria crit = session.createCriteria(ExpressDistribution.class);
        crit.setProjection(Projections.rowCount());
        Long count = (Long) crit.uniqueResult();
        return count.intValue();
    }
    
    public ArrayList<ExpressDistribution> getAllExpressDistribution(){
        Session session = getSession();
        Criteria crit = session.createCriteria(ExpressDistribution.class);
        return (ArrayList<ExpressDistribution>) crit.list();
    }
    

    @Override
    public int getCountForPage() {
        Session session = getSession();
        Criteria crit = session.createCriteria(ExpressDistribution.class);
        crit.setProjection(Projections.rowCount());
        Long count = (Long) crit.uniqueResult();
        return count.intValue();
    }

    @Override
    public ExpressDistribution getCourierByTownId(String town) {
        Session session = getSession();
        Criteria crit = session.createCriteria(ExpressDistribution.class);
        Criteria crit_town = session.createCriteria(MapTown.class);
        crit_town.add(Restrictions.eq("id", town));
        MapTown res_town = (MapTown) crit_town.uniqueResult();
        crit.add(Restrictions.eq("mapTown",res_town ));
        ExpressDistribution courier = (ExpressDistribution) crit.uniqueResult();
        return courier;
    }

    @Override
    public List<ExpressDistribution> getCourierForPageByDistrict(String district, int offset, int length) {
        Session session = getSession();
        List<MapTown> townList = getTownByDistrict(district);
        Criteria crit = session.createCriteria(ExpressDistribution.class);
        crit.add(Restrictions.in("mapTown", townList));
        if(townList.size()>=(offset+length)){
            crit.setFirstResult(offset);
            crit.setMaxResults(length);
        }
        else if(townList.size()<(offset+length)&&townList.size()>=offset){
            crit.setFirstResult(offset);
            crit.setMaxResults(townList.size());
        }
        else{
            return null;
        }
        
        crit.addOrder(Order.asc("id"));
        List<ExpressDistribution> courierList = crit.list();
        return courierList;
//        List<ExpressDistribution> courierList = getCouriersByDistrict(district);
//        List<ExpressDistribution> resList = new ArrayList<ExpressDistribution>();
//        for(int i = offset;i<(offset+length);i++){
//            if(i==courierList.size()){
//                break;
//            }
//            resList.add(courierList.get(i));
//        }
//        return resList;
    }

    @Override
    public List<ExpressDistribution> getCourierForPageByCity(String city, int offset, int length) {
        Session session = getSession();
        List<MapTown> townList = getTownByCity(city);
        Criteria crit = session.createCriteria(ExpressDistribution.class);
        crit.add(Restrictions.in("mapTown", townList));
        if(townList.size()>=(offset+length)){
            crit.setFirstResult(offset);
            crit.setMaxResults(length);
        }
        else if(townList.size()<(offset+length)&&townList.size()>=offset){
            crit.setFirstResult(offset);
            crit.setMaxResults(townList.size());
        }
        else{
            return null;
        }
        crit.addOrder(Order.asc("id"));
        List<ExpressDistribution> courierList = crit.list();
        return courierList;
//        List<ExpressDistribution> courierList = getCourierForPageByCity(city);
//        List<ExpressDistribution> resList = new ArrayList<ExpressDistribution>();
//        for(int i = offset;i<(offset+length);i++){
//            if(i==courierList.size()){
//                break;
//            }
//            resList.add(courierList.get(i));
//        }
//        return resList;
    }

    @Override
    public List<ExpressDistribution> getCourierForPageByProvince(String province, int offset, int length) {
        Session session = getSession();
        List<MapTown> townList = getTownByProvince(province);
        Criteria crit = session.createCriteria(ExpressDistribution.class);
        crit.add(Restrictions.in("mapTown", townList));
        if(townList.size()>=(offset+length)){
            crit.setFirstResult(offset);
            crit.setMaxResults(length);
        }
        else if(townList.size()<(offset+length)&&townList.size()>=offset){
            crit.setFirstResult(offset);
            crit.setMaxResults(townList.size());
        }
        else{
            return null;
        }
        crit.addOrder(Order.asc("id"));
        List<ExpressDistribution> courierList = crit.list();
        return courierList;
    }
    
    @Override
    public List<ExpressDistribution> getCourierForPage(int offset, int length) {
        Session session = getSession();
        Criteria crit = session.createCriteria(ExpressDistribution.class);
        crit.setFirstResult(offset);
        crit.setMaxResults(length);
        crit.addOrder(Order.asc("id"));
        List<ExpressDistribution> courierList = crit.list();
        return courierList;
    }

    @Override
    public List<ExpressDistribution> getCouriersByDistrict(String district) {
        Session session = getSession();
        List<ExpressDistribution> courierList = new ArrayList<ExpressDistribution>();
        Criteria crit = session.createCriteria(ExpressDistribution.class);
        
        Criteria crit_dis = session.createCriteria(MapDistrict.class);
        crit_dis.add(Restrictions.eq("id", district));
        MapDistrict res_dis = (MapDistrict) crit_dis.uniqueResult();
        
        Criteria crit_town = session.createCriteria(MapTown.class);
        crit_town.add(Restrictions.eq("mapDistrict", res_dis));
        crit_town.addOrder(Order.asc("id"));
        List<MapTown> res_town = crit_town.list();
        
        for(MapTown t:res_town){
            System.out.println("========================= 111111111");
            courierList.add(getCourierByTownId(t.getId()));
        }
        return courierList;
    }

    @Override
    public List<ExpressDistribution> getCourierForPageByCity(String city) {
        Session session = getSession();
        List<ExpressDistribution> courierList = new ArrayList<ExpressDistribution>();
        Criteria crit = session.createCriteria(ExpressDistribution.class);
        
        Criteria crit_city = session.createCriteria(MapCity.class);
        crit_city.add(Restrictions.eq("id", city));
        MapCity res_city = (MapCity) crit_city.uniqueResult();
        
        Criteria crit_dis = session.createCriteria(MapDistrict.class);
        crit_dis.add(Restrictions.eq("mapCity", res_city));
        crit_dis.addOrder(Order.asc("id"));
        List<MapDistrict> res_dis = crit_dis.list();
        
        for(MapDistrict d:res_dis){
            courierList.addAll(getCouriersByDistrict(d.getId()));
        }
        return courierList;
    }

    @Override
    public List<ExpressDistribution> getCourierForPageByProvince(String province) {
        Session session = getSession();
        List<ExpressDistribution> courierList = new ArrayList<ExpressDistribution>();
        Criteria crit = session.createCriteria(ExpressDistribution.class);
        
        Criteria crit_province = session.createCriteria(MapProvince.class);
        crit_province.add(Restrictions.eq("id", province));
        MapProvince res_pro = (MapProvince) crit_province.uniqueResult();
        
        Criteria crit_city = session.createCriteria(MapCity.class);
        crit_city.add(Restrictions.eq("mapProvince", res_pro));
        crit_city.addOrder(Order.asc("id"));
        List<MapCity> res_city = crit_city.list();
        
        for(MapCity c:res_city){
            courierList.addAll(getCourierForPageByCity(c.getId()));
        }
        return courierList;
    }

    @Override
    public boolean changeCourier(MapTown town,Employee emp) {
        Session session = getSession();
        boolean isSuccess = false;
        Criteria crit = session.createCriteria(ExpressDistribution.class);
        crit.add(Restrictions.eq("mapTown", town));
        ExpressDistribution exp = (ExpressDistribution) crit.uniqueResult();
        exp.setemployee(emp);
        Transaction trans = null;
        try{
            trans = session.beginTransaction();
            session.update(exp);
            trans.commit();
            session.flush();
            isSuccess = true;
        }catch(Exception e){
            e.printStackTrace();
            if(trans!=null)
                trans.rollback();
            isSuccess = false;
        }
        return isSuccess;
    }

    @Override
    public boolean deleteCourier(MapTown town) {
        Session session = getSession();
        boolean isSuccess = false;
        Criteria crit = session.createCriteria(ExpressDistribution.class);
        crit.add(Restrictions.eq("mapTown", town));
        ExpressDistribution exp = (ExpressDistribution) crit.uniqueResult();
        exp.setemployee(null);
        Transaction trans = null;
        try{
            trans = session.beginTransaction();
            session.update(exp);
            trans.commit();
            session.flush();
            isSuccess = true;
        }catch(Exception e){
            e.printStackTrace();
            if(trans!=null)
                trans.rollback();
            isSuccess = false;
        }
        return isSuccess;
    }
    
    private List<MapTown> getTownByProvince(String pid) {
        Session session = getSession();
        
        Criteria crit_province = session.createCriteria(MapProvince.class);
        crit_province.add(Restrictions.eq("id", pid));
        MapProvince res_pro = (MapProvince) crit_province.uniqueResult();
        
        Criteria crit_city = session.createCriteria(MapCity.class);
        crit_city.add(Restrictions.eq("mapProvince", res_pro));
        List<MapCity> res_city = crit_city.list();
        
        Criteria critDis = session.createCriteria(MapDistrict.class);
        critDis.add(Restrictions.in("mapCity", res_city));
        List<MapDistrict> districts = critDis.list();
        
        Criteria crit_town = session.createCriteria(MapTown.class);
        crit_town.add(Restrictions.in("mapDistrict", districts));
        crit_town.addOrder(Order.asc("id"));
        List<MapTown> towns = crit_town.list();
        
        return towns;
    }
    
    private List<MapTown> getTownByDistrict(String did) {
        Session session = getSession();
        
        Criteria crit_district = session.createCriteria(MapDistrict.class);
        crit_district.add(Restrictions.eq("id", did));
        MapDistrict res_dis = (MapDistrict) crit_district.uniqueResult();
        
        Criteria crit_town = session.createCriteria(MapTown.class);
        crit_town.add(Restrictions.eq("mapDistrict", res_dis));
        crit_town.addOrder(Order.asc("id"));
        List<MapTown> towns = crit_town.list();
        return towns;
    }
    
    private List<MapTown> getTownByCity(String cid) {
        Session session = getSession();
        
        Criteria crit_city = session.createCriteria(MapCity.class);
        crit_city.add(Restrictions.eq("id", cid));
        MapCity res_city = (MapCity) crit_city.uniqueResult();
        
        Criteria crit_district = session.createCriteria(MapDistrict.class);
        crit_district.add(Restrictions.eq("mapCity", res_city));
        List<MapDistrict> res_dis = crit_district.list();
        
        Criteria crit_town = session.createCriteria(MapTown.class);
        crit_town.add(Restrictions.in("mapDistrict", res_dis));
        crit_town.addOrder(Order.asc("id"));
        List<MapTown> towns = crit_town.list();
        return towns;
    }
}
